#ifndef __HANDLEEVENT_H__
#define __HANDLEEVENT_H__

#include "pthreadpool.h"
#include "openssl.h"

class HandleEvent 
{
public:

  static void handleConn(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_)
  		return;
  
  	//处理连接
  	struct sockaddr_in peer;
  	socklen_t peer_len = 0;
  	int clientfd = SockOpt::Accept(tk->fd_, (void*)&peer, (void*)&peer_len);
  	if (clientfd <= 0)
  	{
  		LOG_ERROR("FFL[%s:%s:%u] accpet fail sock_fd_:%u, clientfd:%u", LOG_FFL, tk->fd_, clientfd);
  	}
  	else
  	{
  		std::cout << "get a link..." << tk->fd_ << ":" << clientfd << std::endl;
  		//bool ret = pThreadPool::getInstance()->addThreadEpoll(clientfd);
  		bool ret = pThreadPool::getInstance()->addThreadEpollNew(clientfd);
  		if (!ret)
  		{
  			LOG_ERROR("FFL[%s:%s:%u] addThreadEpoll fail sock_fd_:%u", LOG_FFL, clientfd);
  		}
  	}
  
  }
  
  static void handleSend(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_ || !tk->epollfd_ || !tk->endpoint_)
  		return;
  
  	tk->endpoint_->makeResponse();
  	tk->endpoint_->sendResponse();
  
  	LOG_INFO("FFL[%s:%s:%u] send finish fd:%d",LOG_FFL,  tk->fd_);
  	delete tk->endpoint_;
  	tk->endpoint_ = nullptr;
    pThreadPool::getInstance()->subEpollSockNum(tk->idx_);
  	close(tk->fd_);
  	delete tk;
  	tk = nullptr;
  }
  
  static void handleRecv(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_ || !tk->epollfd_)
  		return;
  
  	char buff[MSG_LEN] = { 0 };
  	int num = SockOpt::Recv(tk->fd_, buff, MSG_LEN - 1, 0);
  	if (num > 0)
  	{
  		if (num >= MSG_MAXLEN)
  		{
  			buff[MSG_MAXLEN - 1] = '\0';
  			num = MSG_MAXLEN;
  			LOG_ERROR("FFL[%s:%s:%u] msg len is small", LOG_FFL);
  		}
  		else
  		{
  			buff[num] = '\0';
  		}
  		//修改事件为写就绪
  		//解析协议，
  		tk->endpoint_ = new HttpEndPoint(tk->fd_);
  		tk->endpoint_->parseHttpMsg(buff, num);
  
  		tk->et_ = (void*)handleSend;
  		EpollOpt::ModEpoll(tk->epollfd_, tk->fd_, EPOLLOUT, tk);
  	}
  	else if (num == 0)
  	{
  		std::cout << "client close" << std::endl;
  		EpollOpt::DelEpoll(tk->epollfd_, tk->fd_);
  		close(tk->fd_);
  		delete tk;
  	}
  	else
  	{
  		std::cout << "recv fail" << std::endl;
  	}
  
  }

  //https 加SSL/TLS验证
  static void handleOpensslConn(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_)
  		return;

  	struct sockaddr_in peer;
  	socklen_t peer_len = 0;
  	int clientfd = SockOpt::Accept(tk->fd_, (void*)&peer, (void*)&peer_len);
  	if (clientfd <= 0)
  	{
  		LOG_ERROR("FFL[%s:%s:%u] accpet fail sock_fd_:%u, clientfd:%u", LOG_FFL, tk->fd_, clientfd);
  	}
  	else
  	{
  		std::cout << "openssl get a link..." << tk->fd_ << ":" << clientfd << std::endl;

      {
        int index = 0;
        int epollfd = pThreadPool::getInstance()->getThreadEpollfd(index);
        if(epollfd < 0)
        {
          std::cout << "get epollfd fail" << std::endl;
          LOG_ERROR("FFL[%s:%s:%d] get epollfd fail", LOG_FFL);
          return;
        }
        task* newtk = new task;
        newtk->ssl_ = SSL_new(OpenSSL::ctx_);
        if(!newtk->ssl_)
        {
          delete newtk;
          std::cout << "new ssl fail" << std::endl;
          LOG_ERROR("FFL[%s:%s:%d] new ssl fail", LOG_FFL);
          return;
        }
        //进行握手
        OpenSSL::sslSetfd(newtk->ssl_, clientfd);
        if(OpenSSL::sslAccept(newtk->ssl_) < 0)
        {
          delete newtk;
          std::cout << "ssl accept fail" << std::endl;
          LOG_ERROR("FFL[%s:%s:%d] ssl accept fail", LOG_FFL);
          return;
        }
        
        std::cout << "ssl accept success ..." << std::endl;
        pThreadPool::getInstance()->addEpollSockNum(index);

        newtk->idx_ = index;
	      newtk->epollfd_ = epollfd;
	      newtk->fd_ = clientfd;
	      newtk->et_ = (void*)HandleEvent::handleOpensslRecv;
	      EpollOpt::AddEpoll(epollfd, clientfd, EPOLLIN, (void*)newtk);
      }
  		//bool ret = pThreadPool::getInstance()->addThreadEpoll(clientfd);
  		//bool ret = pThreadPool::getInstance()->addThreadEpollNew(clientfd);
  		//if (!ret)
  		//{
  			//LOG_ERROR("FFL[%s:%s:%u] addThreadEpoll fail sock_fd_:%u", LOG_FFL, clientfd);
  		//}
  	}
  }

  static void handleOpensslSend(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_ || !tk->epollfd_ || !tk->endpoint_)
  		return;
  
  	tk->endpoint_->makeResponse();
  	//tk->endpoint_->sendResponse();
  	tk->endpoint_->sendOpensslResp();
  
  	LOG_INFO("FFL[%s:%s:%u] send finish fd:%d",LOG_FFL,  tk->fd_);
  	delete tk->endpoint_;
  	tk->endpoint_ = nullptr;

    //关闭ssl连接
    SSL_shutdown(tk->ssl_);
    SSL_free(tk->ssl_);

    pThreadPool::getInstance()->subEpollSockNum(tk->idx_);
  	close(tk->fd_);
  	delete tk;
  	tk = nullptr;
  }

  static void handleOpensslRecv(void* arg)
  {
  	task* tk = (task*)arg;
  	if (!tk || !tk->fd_ || !tk->epollfd_)
  		return;
  
  	char buff[MSG_LEN] = { 0 };
  	int num = OpenSSL::sslRead(tk->ssl_, buff, MSG_LEN - 1);
  	if (num > 0)
  	{
  		if (num >= MSG_MAXLEN)
  		{
  			buff[MSG_MAXLEN - 1] = '\0';
  			num = MSG_MAXLEN;
  			LOG_ERROR("FFL[%s:%s:%u] msg len is small", LOG_FFL);
  		}
  		else
  		{
  			buff[num] = '\0';
  		}
  		//修改事件为写就绪
  		//解析协议，
  		tk->endpoint_ = new HttpEndPoint(tk->fd_, tk->ssl_);
  		tk->endpoint_->parseHttpMsg(buff, num);
  
  		tk->et_ = (void*)handleOpensslSend;
  		EpollOpt::ModEpoll(tk->epollfd_, tk->fd_, EPOLLOUT, tk);
  	}
  	else if (num == 0)
  	{
  		std::cout << "client close" << std::endl;
  		EpollOpt::DelEpoll(tk->epollfd_, tk->fd_);
      if(tk->ssl_)
      {
        SSL_shutdown(tk->ssl_);
        SSL_free(tk->ssl_);
      }
  		close(tk->fd_);
  		delete tk;
  	}
  	else
  	{
  		std::cout << "recv fail" << std::endl;
      EpollOpt::DelEpoll(tk->epollfd_, tk->fd_);
      if(tk->ssl_)
      {
        SSL_shutdown(tk->ssl_);
        SSL_free(tk->ssl_);
      }
      close(tk->fd_);
      delete tk;
  	}

  }

};
  
#endif
